import sys
from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtCore import Qt
import pandas as pd
class TableModel(QtCore.QAbstractTableModel):
    def __init__(self, data):
        super(TableModel, self).__init__()
        self._data = data
        self.properties=[]
    def setDataFrame(self,data,properties=[]):
        self.beginResetModel()
        self._data=data
        self.properties=properties
        self.endResetModel()
    def getObject(self, index):
        if not index.isValid():
            return None
        objectIndex = index.row()
        try:
            return self._data[objectIndex]
        except IndexError:
            return None
    def getObjectRow(self, row):
        try:
            return self._data[row]
        except IndexError:
            return None
    def getProperty(self, index):
        if not index.isValid():
            return None
        propertyIndex = index.column()
        try:
            return self.properties[propertyIndex]
        except IndexError:
            return None        
    def data(self, index, role):
        if role == Qt.DisplayRole:
            value = self._data.iloc[index.row(), index.column()]
            return str(value)
    def setData(self, index, value, role=Qt.EditRole):
        if not index.isValid():
            logging.info("index invalid")
            return False
        obj = self.getObject(index)
        prop = self.getProperty(index)
        if (obj is None) or (prop is None):
            logging.info("obj is None or prop is None")
            return None
        try:
            if role == Qt.EditRole:
                logging.info(type(value))
                # setAttrRecursive(obj, prop['attr'], value)
                obj[index.column()]=value
                return True
        except:
            traceback.print_exc()
            return False
        return False

    def flags(self, index):
        flags = QtCore.QAbstractTableModel.flags(self, index)
        if not index.isValid():
            return flags
        prop = self.getProperty(index)
        if prop is None:
            return flags
        flags |= Qt.ItemIsEnabled
        flags |= Qt.ItemIsSelectable
        mode = prop.get('mode', "Read/Write")
        if "Write" in mode:
            flags |= Qt.ItemIsEditable
        return flags
    def rowCount(self, index):
        return self._data.shape[0]

    def columnCount(self, index):
        return self._data.shape[1]

    def headerData(self, section, orientation, role):
        # section is the index of the column/row.
        if role == Qt.DisplayRole:
            if orientation == Qt.Horizontal:
                return str(self._data.columns[section])

            if orientation == Qt.Vertical:
                return str(self._data.index[section])


class MainWindow(QtWidgets.QMainWindow):

    def __init__(self):
        super().__init__()

        self.table = QtWidgets.QTableView()

        data = pd.DataFrame([
          [1, 9, 2],
          [1, 0, -1],
          [3, 5, 2],
          [3, 3, 2],
          [5, 8, 9],
        ], columns = ['A', 'B', 'C'], index=['Row 1', 'Row 2', 'Row 3', 'Row 4', 'Row 5'])

        self.model = TableModel(data)
        self.table.setModel(self.model)

        self.setCentralWidget(self.table)


app=QtWidgets.QApplication(sys.argv)
window=MainWindow()
window.show()
app.exec()